<?
	/**
	 * UCModInvite.php
	 * 邀请逻辑
	 *
	 * Copyright (c) 2010 snda.com - Web Development Center
	 * @author: Gu Shougang <gushougang@snda.com>
	 */
	
	require_once(dirname(__FILE__).'/../../config/invite/UCConfInvite.php');
	require_once(dirname(__FILE__).'/../../models/store/UCModStore.php');
	require_once(dirname(__FILE__).'/../../models/store/UCModPanel.php');
	require_once(dirname(__FILE__).'/../../libraries/UCLibPDOFactory.php');
	require_once(dirname(__FILE__).'/../../libraries/UCLibKVDB.php');
	require_once(dirname(__FILE__).'/../../libraries/UCLibCache.php');
	require_once(dirname(__FILE__).'/../../models/relation/UCModRelation.php');
	require_once(dirname(__FILE__).'/../../models/user/UCModUserSearcher.php');
	require_once(dirname(__FILE__).'/../../models/message/UCModMessageMgr.php');
	require_once(dirname(__FILE__).'/../../libraries/UCLibStat.php');
	require_once(dirname(__FILE__).'/../../models/shorten/UCModShorten.php');
	
	class UCModInvite
	{
		protected $_error = '';
		private $_included = false;
		
		private static $instance = null;
		
		/**
		 * 构造函数
		 * 调用__construct()
		 */
		public function UCModInvite()
		{
			$this->__construct();
		}
		
		/**
		 * 构造函数
		 */
		public function __construct()
		{
			// Do nothing
		}
		
		/**
		 * 读取QQ好友列表
		 * @param int $qqNumber 用户QQ号码
		 * @param string $qqPassword 用户QQ密码
		 * @return mixed
		 */
		protected function _getQQFriendListByQQNum($qqNumber, $qqPassword)
		{
			$qqNumber = trim($qqNumber);
			$qqPassword = trim($qqPassword);
			if(strlen($qqNumber) == 0 || strlen($qqPassword) == 0 || !is_numeric($qqNumber))
			{
				return UC_QQ_PARAMS_ERROR;
			}
			
			// TODO: Implementation
			
			return $qqFriendList;
		}
		
		/**
		 * 读取MSN好友列表
		 * @param string $msnAddress 用户MSN地址
		 * @param string $msnPassword 用户MSN密码
		 * @return array
		 */
		public function getMSNFriendListByMSNAddress($msnAddress, $msnPassword)
		{
			$msnAddress = trim($msnAddress);
			$msnPassword = trim($msnPassword);
			if(strlen($msnAddress) == 0 || strlen($msnPassword) == 0)
			{
				return array();
			}
			
			if(!is_email($msnAddress))
			{
				return array();
			}
			
			include_once(dirname(__FILE__).'/../../libraries/Utils/UCLibMSN.php');

			$msn = new UCLibMSN();
			$msn->connect($msnAddress, $msnPassword);
			
			$msn_list = $msn->getAddressBook();
			
			$msn_return_list = array();
			
			foreach($msn_list as $msn => $msnInfo)
			{
				//var_dump($msnInfo);
				$msnInfo['group'] = trim($msnInfo['group']);
				if(strlen($msnInfo['group']))
				{
					$msn_return_list[$msnInfo['group']][$msn] = $msnInfo['name'];
				}
			}
			unset($msn_list);
			
			return $msn_return_list;
		}
		
		/**
		 * 读取邮件通讯录
		 * @param string $emailAddress 用户邮箱地址
		 * @param string $emailPassword 用户邮箱密码
		 * @return mixed
		 */
		public function getEmailContactListByEmailAddress($emailAddress, $emailPassword)
		{
			$emailAddress = trim($emailAddress);
			$emailPassword = trim($emailPassword);
			if(strlen($emailAddress) == 0 || strlen($emailPassword) == 0)
			{
				return false;
			}
			
			if(!is_email($emailAddress))
			{
				return false;
			}
			
			$emailDomain = strtolower(substr($emailAddress, strpos($emailAddress, '@') + 1, strlen($emailAddress) - strpos($emailAddress, '@')));
			switch($emailDomain)
			{
				case 'gmail.com':			// OK
				case '21cn.com':			// sdotest@21cn.com / 124028			OK
				case '126.com':			// sdotest@126.com / 147258369		OK
				case '163.com':			// sdotesttest@163.com / 147258369	OK
				//case 'eyou.com':			// sdotest@eyou.com / 147258369
				case 'sina.com':			// OK
				case 'sohu.com':			// sdotesttest@sohu.com / 147258369		OK
				case 'tom.com':			// sdotest@tom.com / 147258369			OK
				case 'yahoo.cn':			// sdotesttest@yahoo.cn / 147258369		OK
					include_once(dirname(__FILE__).'/../../libraries/Utils/Emails/'. str_replace('.', '_', $emailDomain) .'.php');
					
					$email = new Email();
					return $email->get_contacts($emailAddress, $emailPassword);
				default:
					return UC_DO_NOT_SUPPORT_EMAIL;
			}
		}
		
		/**
		 * 生成邀请URL
		 * @param int $userId 主动发起邀请的用户Id
		 * @param string $callBackUrl 回调地址
		 * @param int $appId 标示该邀请是由哪里发起的,0 标示是UC发起,有其他值标示开放平台的应用ID
		 * @return string
		 */
		public static function makeInviteUrl($userId, $callBackUrl = '', $appId = 0)
		{
			$userId = trim($userId);
			$callBackUrl = trim($callBackUrl);
			$appId =trim($appId);
			
			if(strlen($userId) == 0 || !is_numeric($userId))
			{
				return '';
			}
			
			if(strlen($callBackUrl) && !is_url($callBackUrl))
			{
				//TODO:
				return '';
			}
			
			if(strlen($appId) == 0)
			{
				$appId = 0;
			}
			
			if(!is_numeric($appId) || $appId < 0)
			{
				return '';
			}
			
			if(strlen($callBackUrl) == 0)
			{
				if($appId > 0)
				{
					//$app_id = UCModStore::getInstance()->getAppIdByOppId($appId);
					$app_id = $appId;
					$app_info = UCModStore::getInstance()->getApp($app_id);
					
					if(!is_array($app_info))
					{
						//无效应用
						return '';
					}
									
					$callBackUrl = UCModPanel::getLink($app_info, TRUE);
					$callBackUrl .= (strpos($callBackUrl, '?') !== FALSE ? '&' : '?') . 'sdo_from=' . $userId . '&sdo_new=1';
				}
			}
			
			//首先判断数据库中是否有用户已经生成的链接邀请码
			$inviteCode = UCModInvite::getFreeTicketIdBySDOAccount($userId, $appId);
			
			//var_dump($appId);
			//var_dump($inviteCode);
			
			if(!strlen($inviteCode))
			{
				//$inviteCode = $this->makeRandNum($userId);
				$pdo = UCLibPDOFactory::getPDO('request', $userId, 'invite2dbconfig');
				$inviteCode = str_replace('-', '', $pdo->gen_uuid());
				
				//把新生成的链接邀请码存到数据库中
				$r = UCModInvite::insertSDOAccountFreeTicketId($userId, $inviteCode, $appId, $callBackUrl);
			}
			
			$inviteUrl = UC_INVITE_URL . 'code=' . $inviteCode . '&from=' . $userId;
			
			$shorten = new UCModShorten();
			
			return $shorten->makeShortUrlByLongUrl($inviteUrl);
		}
		
		/**
		 * 生成邀请码
		 * @param int $userId 主动发起邀请的用户Id
		 * @return string
		 */
		public function makeRandNum($userId)
		{
			if(!is_numeric($userId))
			{
				return '';
			}
			return substr(md5($userId . '@' . time() . '|' . UC_INVITE_ENCRYPTION_KEY), 5, 16);
		}
		
		/**
		 * 验证邀请码合法性
		 * @param string $code 被邀请用户收到的验证码
		 * @param string $linkhash 针对链接邀请而生成的Key
		 * 
		 * @return array
		 */
		public function checkInviteRequest($code, $linkhash, $userId)
		{
			$code = trim($code);
			$linkhash = trim($linkhash);
			
			if(strlen($code) == 0)
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo = UCLibPDOFactory::getPDO('request', $userId, 'invite2dbconfig');
			
			//到链接邀请表中查询一下
			$link_info = $this->getSDOAccountByFreeTicketId($code);
			$user_id = $link_info['user_id'];
			$app_id = $link_info['app_id'];
			$callbackurl = $link_info['callbackurl'];
			
			if(strlen($user_id) == 0)
			{
				//echo 'a<br />';
				//说明是邮件邀请
				$mail_sql = 'SELECT `user_id`, `invite_type`, `remark`, `ticket_status`, `callback_url`, `app_id` FROM ' . $pdo->database . '.' . $pdo->table . ' WHERE `ticket_id` = ? AND `ticket_status` != 4 AND `user_id` = ?';
				$params = array($code, $userId);
				$h = $pdo->query_one_row_with_prepare($mail_sql, $params);
				if($h === NULL)
				{
					//echo 'b<br />';
					//没有记录
					return '';
				}
				else if($h === FALSE)
				{
					//echo 'c<br />';
					//系统错误
					$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
				else
				{
					//echo 'd<br />';
					return array('user_id' => $h['user_id'], 'callbackurl' => $h['callback_url'], 'app_id' => $h['app_id'], 'invite_type' => $h['invite_type']);
				}
			}
			else
			{
				//echo 'e<br />';
				//说明是链接邀请
				if($app_id >= 0)
				{
					//echo 'f<br />';
					//说明是普通链接邀请
					if(strlen($linkhash))
					{
						//echo 'g<br />';
						//有linkhash,说明是已经登陆过的链接请求,过来验证
						$link_sql = 'SELECT `user_id`, `invite_type`, `remark`, `ticket_status`, `callback_url`, `app_id` FROM ' . $pdo->database . '.' . $pdo->table . ' WHERE `ticket_id` = ? AND `remark` = ? AND `user_id` = ?';
						$params = array($code, $linkhash, $userId);
						$h = $pdo->query_one_row_with_prepare($link_sql, $params);
						if($h === NULL)
						{
							//echo 'h<br />';
							//没有记录
							return '';
						}
						else if($h === FALSE)
						{
							//echo 'i';
							//系统错误
							$this->_error = '系统错误:数据库错误';
							return FALSE;
						}
						else
						{
							//echo 'j';
							if($h['ticket_status'] == INVITE_OVER)
							{
								//echo 'k';
								//没有记录
								return '';
							}
							//echo 'l';
							return array('user_id' => $h['user_id'], 'callbackurl' => $h['callback_url'], 'app_id' => $h['app_id'], 'invite_type' => $h['invite_type']);
						}
					}
					else
					{
						//echo 'm';
						//没有linkhash,说明是未登陆过,准备要来注册的请求,看看inviterequest表里有没有
						$link_sql = 'SELECT `user_id`, `invite_type`, `remark`, `ticket_status`, `callback_url`, `app_id` FROM ' . $pdo->database . '.' . $pdo->table . ' WHERE `ticket_id` = ? AND `user_id` = ? AND `remark` = ""';
						$params = array($code, $userId);
						$h = $pdo->query_one_row_with_prepare($link_sql, $params);

						if($h === FALSE)
						{
							//echo 'n';
							//系统错误
							$this->_error = '系统错误:数据库错误';
							return FALSE;
						}
						else
						{
							//echo 'o';
							if($h === NULL)
							{
								//echo 'p';
								//没有记录, 说明没有生成过linkhash
							}
							else
							{
								//echo 'q';
								if($h['ticket_status'] == INVITE_OVER || strlen($h['remark']))
								{
									//echo 'r';
									//有记录,但是说明生成的linkhash已经过期了
									//return '';
								}
								else
								{
									//echo 's';
									//说明这个邀请码的状态不是过期或者已经生成过linkhash,这里就表示数据不正常了.
									//系统错误, Should Not Be Here
									$this->_error = '系统错误:数据库错误';
									return FALSE;
								}
							}
							
							//准备添加新的linkhash
							$link_request_hashkey = $this->makeRandNum($user_id);
							
							$invite_type = INVITE_TYPE_APP_LINK;		//APP链接邀请
							if($app_id == 0)
							{
								$invite_type = INVITE_TYPE_LINK;	//普通链接邀请
							}
							
							$params = array(
								'ticket_id' => $code,
								'user_id' => $user_id,
								'invite_type' => $invite_type,		//链接邀请
								'register_datetime' => date('Y-m-d H:i:s'),
								'remark' => $link_request_hashkey,
								'app_id' => $app_id,
							);
							
							if(strlen($callbackurl))
							{
								$params['callback_url'] = $callbackurl;
							}
							
							$r = $this->insertInviteRequest($params);
							
							if($r)
							{
								//echo 't';
								return array('user_id' => $user_id, 'linkhash' => $link_request_hashkey, 'callbackurl' => $callbackurl, 'app_id' => $app_id, 'invite_type' => $invite_type);
							}
							else
							{
								//echo 'u';
								$this->_error = '系统错误:数据库错误';
								return FALSE;
							}
						}
					}
				}
				else
				{
					//echo 'v';
					//系统错误, Should Not Be Here
					$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
			}
		}
		
		/**
		 * 将邀请请求插入数据库
		 * @param array $params 字段键值对
		 * @return boolean
		 */
		public function insertInviteRequest($params)
		{
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(!isset($params['user_id']) || strlen($params['user_id']) == 0)
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo = UCLibPDOFactory::getPDO('request', $params['user_id'], 'invite2dbconfig');
			
			if(strlen($params['ticket_id']) == 0)
			{
				$params['ticket_id'] = str_replace('-', '', $pdo->gen_uuid());
			}
			
			$fields = array_keys($params);
			foreach($fields as $field)
			{
				$query_string .= ' ' . $field . '=?,';
			}
			$query_string = trim($query_string, ',');
			
			$h = $pdo->exec_with_prepare('REPLACE INTO ' . $pdo->database . '.' . $pdo->table . ' SET' . $query_string, array_values($params));
			
			if($h)
			{
				if(strlen($params['target_extern_account']))
				{
					$r = $this->setInviteQueue($params['user_id'], $params['ticket_id'], $params['target_extern_account'], $params['app_id']);
					{
						return $r ? TRUE : FALSE;
					}
				}
				
				return TRUE;
			}
			else
			{
				//var_dump($pdo->errorInfo());
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 从数据库中获取邀请请求信息
		 * @param int $userId 用户Id
		 * @param array $params 查询条件参数
		 * @param boolean $need_count 是否只需要显示返回条目数量
		 * @return mixed
		 */
		public function getInviteRequestInfo($userId, $params = array(), $need_count = FALSE, $start = '', $limit = 0)
		{
			$userId = trim($userId);
			
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(strlen($userId) == 0 || !is_numeric($userId))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$query_string = '';
			$fields = array_keys($params);
			foreach($fields as $field)
			{
				$query_string .= ' and ' . $field . '=?';
			}
			
			$pdo = UCLibPDOFactory::getPDO('request', $userId, 'invite2dbconfig');
			
			$select = ($need_count) ? 'COUNT(1) AS num' : '*';
			$sql_string = 'SELECT ' . $select . ' FROM ' . $pdo->database . '.' . $pdo->table . ' WHERE user_id = ?';
			
			if(strlen($query_string))
			{
				$sql_string .= $query_string;
			}
			
			if(!is_numeric($limit))
			{
				return FALSE;
			}
			if($limit > 0)
			{
				if(!is_numeric($start))
				{
					return FALSE;
				}
				if($start < 0)
				{
					return FALSE;
				}
				
				$sql_string .= ' LIMIT ' . $start . ', ' . $limit;
			}
			
			$values = array_values($params);
			array_unshift($values, $userId);
			return $pdo->query_with_prepare($sql_string, $values);				
		}
				
		/**
		 * 更新邀请请求信息
		 * @param int $userId 用户Id
		 * @param string $ticketId 邀请码
		 * @param string $linkhash 针对链接邀请的hashkey
		 * @param array $params 查询条件参数
		 * @return array
		 */
		public function updateInviteRequest($userId, $ticketId, $linkhash = '', $params = array())
		{
			$userId = trim($userId);
			$ticketId = trim($ticketId);
			$linkhash = trim($linkhash);
						
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(!is_numeric($userId))
			{
				$this->_error = '参数错误:用户ID不合法.';
				return FALSE;
			}
			
			if(strlen($ticketId) == 0)
			{
				$this->_error = '参数错误:邀请码为空.';
				return FALSE;
			}
			
			if(empty($params))
			{
				$this->_error = '参数错误:更新条件为空.';
				return FALSE;
			}
			
			$query_string = '';
			$fields = array_keys($params);
			foreach($fields as $field)
			{
				$query_string .= $field . '=?,';
			}
			$value = array_values($params);
			
			$query_string = trim($query_string, ',');
			
			$pdo = UCLibPDOFactory::getPDO('request', $userId, 'invite2dbconfig');
			$sql_string = 'UPDATE ' . $pdo->database . '.' . $pdo->table . ' SET ' . $query_string . ' WHERE ticket_id = ? AND user_id = ?';
			
			array_push($value, $ticketId, $userId);
			
			if(strlen($linkhash))
			{
				$sql_string .= ' and remark = ?';
				array_push($value, $linkhash);
			}

			$h = $pdo->exec_with_prepare($sql_string, $value);
			
			if($h)
			{
				return TRUE;
			}
			else
			{
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 根据SDO账号获取对应外部账号
		 * @param int $user_id 用户Id
		 * @param string $extern_type 外部账号类型
		 * @return string
		 */
		public function getSDOExternAccount($user_id, $extern_type)
		{
			$user_id = trim($user_id);
			$extern_type = trim($extern_type);
			
			$pdo_key = $user_id . '_' . $extern_type;
			$pdo = get_invite_tt_config('SDOAccount_ExternAccount', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_SDOACCOUNT_EXTERNACCOUNT);

			return unserialize($tt->get($pdo['tb_name']));
		}
		
		/**
		 * 将用户SDO账号与外部账号对应关系插入数据库
		 * @param array $params 字段键值对
		 * @return boolean
		 */
		public function insertSDOExternAccount($params)
		{
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(strlen($params['user_id']) == 0 || strlen($params['extern_type']) == 0 || !is_numeric($params['user_id']))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo_key = $params['user_id'] . '_' . $params['extern_type'];
			$pdo = get_invite_tt_config('SDOAccount_ExternAccount', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_SDOACCOUNT_EXTERNACCOUNT);

			$temp_value = unserialize($tt->get($pdo['tb_name']));
			if(!is_array($temp_value))
			{
				$temp_value = array();
			}
			$temp_value[$params['extern_account']] = time();
			
			$r = $tt->put($pdo['tb_name'], serialize($temp_value));
			
			if($r)
			{
				return TRUE;
			}
			else
			{
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 更新SDO账号与外部账号对应关系
		 * @param array $params 字段键值对
		 * @param boolean $delete 是否要删除
		 * @return boolean
		 */
		public function updateSDOExternAccount($params, $delete = FALSE)
		{
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(strlen($params['user_id']) == 0 || strlen($params['extern_type']) == 0 || !is_numeric($params['user_id']))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo_key = $params['user_id'] . '_' . $params['extern_type'];
			$pdo = get_invite_tt_config('SDOAccount_ExternAccount', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_SDOACCOUNT_EXTERNACCOUNT, FALSE);
			$r = $tt->delete($pdo['tb_name']);
			
			if($delete)
			{
				$tt->close();
				if($r)
				{
					return TRUE;
				}
				else
				{
					$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
			}
			
			if($r)
			{
				$temp_value = unserialize($tt->get($pdo['tb_name']));
				if(is_array($temp_value))
				{
					if(strlen($temp_value[$params['extern_account']]) == 0)
					{
						$temp_value[$params['extern_account']] = time();
					}
				}
				else
				{
					$temp_value[$params['extern_account']] = time();
				}
				
				$r = $tt->put($pdo['tb_name'], serialize($temp_value));
				
				$tt->close();
				if($r)
				{
					return TRUE;
				}
				else
				{
					$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
			}
			
			$tt->close();
			$this->_error = '系统错误:数据库错误';
			return FALSE;
		}
		
		/**
		 * 将用户外部好友联系方式插入数据库
		 * @param array $params 字段键值对
		 * @return boolean
		 */
		public function insertUserFriendExternAccount($params)
		{
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(strlen($params['user_id']) == 0 || !is_numeric($params['user_id']))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$fields = array_keys($params);
			foreach($fields as $field)
			{
				$query_string .= ' ' . $field . '=?,';
			}
			$query_string = trim($query_string, ',');
			
			$pdo = UCLibPDOFactory::getPDO('friendexternaccount', $params['user_id'], 'invite2dbconfig');
			$h = $pdo->exec_with_prepare('REPLACE INTO ' . $pdo->database . '.' . $pdo->table . ' SET' . $query_string, array_values($params));
			
			if($h)
			{
				return TRUE;
			}
			else
			{
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 获取某用户所有外部好友联系方式
		 *
		 * @return array
		 */
		public function getUserFriendExternAccount($userId, $params = array(), $need_count = FALSE, $start = '', $limit = 0)
		{
			$userId = trim($userId);
			
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(strlen($userId) == 0 || !is_numeric($userId))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$query_string = '';
			$fields = array_keys($params);
			foreach($fields as $field)
			{
				$query_string .= ' and ' . $field . '=?';
			}
			
			$pdo = UCLibPDOFactory::getPDO('friendexternaccount', $userId, 'invite2dbconfig');
			
			$select = ($need_count) ? 'COUNT(1)' : '*';
			$sql_string = 'SELECT ' . $select . ' FROM ' . $pdo->database . '.' . $pdo->table . ' WHERE user_id = ?';
			
			if(strlen($query_string))
			{
				$sql_string .= $query_string;
			}
			
			if(!is_numeric($limit))
			{
				return FALSE;
			}
			if($limit > 0)
			{
				if(!is_numeric($start))
				{
					return FALSE;
				}
				if($start < 0)
				{
					return FALSE;
				}
				
				$sql_string .= ' LIMIT ' . $start . ', ' . $limit;
			}
			
			$values = array_values($params);
			array_unshift($values, $userId);
			return $pdo->query_with_prepare($sql_string, $values);		
		}
		
		/**
		 * 将用户外部账号与SDO账号对应关系插入数据库
		 * @param array $params 字段键值对
		 * @return boolean
		 */
		public function insertExternAccountSDO($params)
		{
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			if(strlen($params['user_id']) == 0 || !is_numeric($params['user_id']) || strlen($params['extern_account']) == 0 || strlen($params['friend_type']) == 0)
			{				
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			$pdo_key = $params['extern_account'];
			$pdo = get_invite_tt_config('externAccount_SDOAccount', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_EXTERNACCOUNT_SDOACCOUNT);
			
			$temp_value = unserialize($tt->get($pdo['tb_name']));
			if(is_array($temp_value))
			{
				$tt->delete($pdo['tb_name']);
			}
			$r = $tt->put($pdo['tb_name'], serialize(array($params['user_id'], $params['friend_type'], time())));
			
			if($r)
			{
				return TRUE;
			}
			else
			{
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 更新外部账号与SDO账号对应关系
		 * @param array $params 字段键值对
		 * @param boolean $delete 是否要删除
		 * @return boolean
		 */
		public function updateExternAccountSDO($params, $delete = FALSE)
		{
			foreach($params as $k => $v)
			{
				$params[$k] = trim($v);
			}
			
			if(strlen($params['user_id']) == 0 || !is_numeric($params['user_id'] || strlen($params['extern_account']) == 0 || strlen($params['friend_type']) == 0))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo_key = $params['extern_account'];
			$pdo = get_invite_tt_config('externAccount_SDOAccount', $pdo_key);
			
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_EXTERNACCOUNT_SDOACCOUNT, FALSE);
			
			$temp_value = unserialize($tt->get($pdo['tb_name']));
			if(is_array($temp_value))
			{
				$r = $tt->delete($pdo['tb_name']);
			}
			
			if($delete)
			{
				$tt->close();
				if($r)
				{
					return TRUE;
				}
				else
				{
					$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
			}
			
			if($r)
			{
				$r = $tt->put($pdo['tb_name'], serialize(array($params['user_id'], $params['friend_type'], time())));
				
				$tt->close();
				if($r)
				{
					return TRUE;
				}
				else
				{
					$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
			}
			
			$tt->close();
			$this->_error = '系统错误:数据库错误';
			return FALSE;
		}
		
		/**
		 * 根据用户外部账号检查获取SDO账号
		 * @param string $extern_account 外部账号,可以是QQ号码/MSN账号/Email账号
		 * @return array
		 */
		public function getSDOAccountByExternAccount($extern_account)
		{
			$extern_account = trim($extern_account);
			
			if(strlen($extern_account) == 0)
			{
				return FALSE;
			}
			
			$pdo_key = $extern_account;
			$pdo = get_invite_tt_config('externAccount_SDOAccount', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_EXTERNACCOUNT_SDOACCOUNT);
			
			return unserialize($tt->get($pdo['tb_name']));
		}
		
		/**
		 * 根据用户外部账号批量获取SDO账号
		 * @param string $extern_account 外部账号,可以是QQ号码/MSN账号/Email账号,逗号间隔
		 * @return array
		 */
		public function getSDOAccountByExternAccountArray($extern_account)
		{
			$extern_account = trim($extern_account);
			
			if(strlen($extern_account) == 0)
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$account = explode(',', $extern_account);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_EXTERNACCOUNT_SDOACCOUNT, FALSE);
			
			$sdoAccount = array();
			foreach($account as $v)
			{
				$pdo_key = $v;
				$pdo = get_invite_tt_config('externAccount_SDOAccount', $pdo_key);
				$sdoAccount[$v] = $tt->get($pdo['tb_name']);
			}
			
			return $sdoAccount;
		}

		/**
		 * 根据链接邀请码查询对应的用户Id
		 * @param string $ticketId 链接邀请码
		 * @return array
		 */
		public function getSDOAccountByFreeTicketId($ticketId)
		{
			$ticketId = trim($ticketId);
			if(strlen($ticketId) == 0)
			{
				return '';
			}
			
			$pdo_key = $ticketId;
			$pdo = get_invite_tt_config('ticketId_SDOAccount', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_TICKETID_SDOACCOUNT);
			
			return unserialize($tt->get($pdo['tb_name']));
		}

		/**
		 * 根据用户Id查询对应的链接邀请码
		 * @param string $userId 链接邀请码
		 * @param int $appId 发起方ID
		 * @return string
		 */
		public function getFreeTicketIdBySDOAccount($userId, $appId = 0)
		{
			$userId = trim($userId);
			$appId = trim($appId);
			if(strlen($userId) == 0 || !is_numeric($userId) || strlen($appId) == 0 || !is_numeric($appId))
			{
				return '';
			}
			
			$pdo_key = $userId . '_' . $appId;
			$pdo = get_invite_tt_config('SDOAccount_ticketId', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_SDOACCOUNT_TICKETID);
			
			return $tt->get($pdo['tb_name']);
		}
		
		/**
		 * 将链接邀请码与用户Id的对应关系插入数据库
		 * @param string $userId 用户Id
		 * @param string $ticketId 链接邀请码
		 * @param int $appId 标示该邀请是由哪里发起的,0 标示是UC发起,有其他值标示开放平台的应用ID
		 * @param string $callBackUrl 回调地址
		 * @return boolean
		 */
		public static function insertSDOAccountFreeTicketId($userId, $ticketId, $appId = 0, $callBackUrl)
		{
			$ticketId = trim($ticketId);
			$userId = trim($userId);
			$appId = trim($appId);
			$callBackUrl = trim($callBackUrl);
			
			if(strlen($ticketId) == 0 || strlen($userId) == 0 || strlen($appId) == 0)
			{
				//$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo_key = $userId . '_' . $appId;
			$pdo = get_invite_tt_config('SDOAccount_ticketId', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_SDOACCOUNT_TICKETID);
			
			$r = $tt->put($pdo['tb_name'], $ticketId);
			
			if($r)
			{
				$pdo_key = $ticketId;
				$pdo = get_invite_tt_config('ticketId_SDOAccount', $pdo_key);
				$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_TICKETID_SDOACCOUNT);
				
				$r = $tt->put($pdo['tb_name'], serialize(array('user_id' => $userId, 'app_id' => $appId, 'callbackurl' => $callBackUrl)));
				if($r)
				{
					return TRUE;
				}
				else
				{
					//$this->_error = '系统错误:数据库错误';
					return FALSE;
				}
			}
			else
			{
				//$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 根据邀请码查询对应的callbackurl
		 * @param string $ticketId 邀请码
		 * @return string
		 */
		public function getCallBackUrlByTicketId($ticketId = '')
		{
			$ticketId = trim($ticketId);
			if(strlen($ticketId) == 0)
			{
				return '';
			}
			
			$pdo_key = $ticketId;
			$pdo = get_invite_tt_config('ticketId_CallBackUrl', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_STATISTICS);
			
			return $tt->get($pdo['tb_name']);
		}
		
		/**
		 * 将邀请码与callbackurl的对应关系插入数据库
		 * @param string $ticketId 邀请码
		 * @param string $callBackUrl 回调地址
		 * @return boolean
		 */
		public function insertTicketIdCallBackUrl($ticketId, $callBackUrl)
		{
			$ticketId = trim($ticketId);
			$callBackUrl = trim($callBackUrl);
			
			if(strlen($ticketId) == 0 || strlen($callBackUrl) == 0)
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$pdo_key = $ticketId;
			$pdo = get_invite_tt_config('ticketId_CallBackUrl', $pdo_key);
			$tt = new UCLibKVDB(UCLibKVDB::$CHANNEL_STATISTICS);
			$r = $tt->put($pdo['tb_name'], $callBackUrl);
			
			if($r)
			{
				return TRUE;
			}
			else
			{
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 根据外部账号查询是否是SDO账号,并判断是否是好友
		 * @param int $currUserId 当前用户Id
		 * @param array $friendList 需要判断的用户列表
		 * @return array
		 */
		public function checkSDOAccountWithRelation($currUserId, $friendList)
		{
			$currUserId = trim($currUserId);
			if(strlen($currUserId) == 0 || !is_numeric($currUserId))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			if(empty($friendList))
			{
				$this->_error = '参数错误:为空或不合法.';
				return FALSE;
			}
			
			$sdo_user_list = array();
			$sdo_user_return = array(array(), array(array(), array()));		//返回值列表
			$sdo_user_id = array();
			
			//把所有SDO账号和非SDO账号分开
			foreach($friendList as $group_name => $group_user_list)
			{
				if(!empty($group_user_list))
				{					
					foreach($group_user_list as $msn => $name)
					{
						$sdo_id = $this->getSDOAccountByExternAccount($msn);
						
						if($sdo_id === FALSE || strlen($sdo_id[0]) == 0)
						{
							//说明不是SDO用户
							$sdo_user_return[0][$group_name][$msn] = $name;
						}
						else
						{
							$sdo_user_list[$group_name][] = array('email' => $msn, 'name' => $name, 'user_id' => $sdo_id[0]);
						}
					}
				}
			}
			
			//在所有SDO账号中区分好友账号和非好友账号
			
			$relation = new UCModRelation($currUserId);
			
			foreach($sdo_user_list as $group_name => $group_user_list)
			{
				if(!empty($group_user_list))
				{
					foreach($group_user_list as $v)
					{
						$r = $relation->getSingleRelationType($v['user_id'], 3);
						if($r)
						{
							$sdo_user_return[1][0][] = $v['user_id'];
						}
						else
						{
							$sdo_user_return[1][1][] = $v;
							$sdo_user_id[] = $v['user_id'];
						}
					}
				}
			}
			
			//对所有已经是好友的SDO账号,取用户名和密码
			$user_info = UCModUserInfo::getUserInfos($sdo_user_id, array(USERINFO_NICKNAME, USERINFO_AVATAR_45));
			//填充信息
			foreach($sdo_user_return[1][1] as &$v)
			{
				$v['user_face'] = $user_info[$v['user_id']][USERINFO_AVATAR_45];
				$v['nickname'] = strlen(trim($user_info[$v['user_id']][USERINFO_NICKNAME])) ? trim($user_info[$v['user_id']][USERINFO_NICKNAME]) : $v['user_id'];
			}
			
			return $sdo_user_return;
		}
		
		/**
		 * 插入/删除邮件队列
		 * @param int $user_id 用户Id
		 * @param string $code 邀请码
		 * @param string $target_extern_account 邮件地址
		 * @param int $app_id 应用Id
		 * @param boolean $del 
		 * @return boolean
		 */
		public function setInviteQueue($user_id, $code, $target_extern_account, $app_id = 0, $del = FALSE)
		{
			$user_id = trim($user_id);
			$code = trim($code);
			$target_extern_account = trim($target_extern_account);
			$app_id = trim($app_id);
			
			if(!is_numeric($user_id) || strlen($user_id) == 0 || strlen($code) == 0 || !is_email($target_extern_account))
			{
				return FALSE;
			}
			
			$pdo = UCLibPDOFactory::getPDO('mailqueue', '', 'invite2dbconfig');
			
			if($del)
			{
				$sql = 'DELETE FROM ' . $pdo->database . '.' . $pdo->table . ' WHERE user_id = ? AND ticket_id = ? AND target_extern_account = ? AND app_id = ?';
			}
			else
			{
				$sql = 'REPLACE INTO ' . $pdo->database . '.' . $pdo->table . ' SET user_id = ?, ticket_id = ?, target_extern_account = ?, app_id = ?';
			}
			
			$h = $pdo->exec_with_prepare($sql, array($user_id, $code, $target_extern_account, $app_id));
			
			if($h)
			{
				return TRUE;
			}
			else
			{
				//var_dump($pdo->errorInfo());
				$this->_error = '系统错误:数据库错误';
				return FALSE;
			}
		}
		
		/**
		 * 读取邮件队列
		 * @param int $start	读取起始位置
		 * @param int $limit	每次读取的量
		 * @return array
		 */
		public function getInviteQueue($start = 0, $limit = 20)
		{
			$start = trim($start);
			$limit = trim($limit);
			
			if(!is_numeric($limit) || !is_numeric($start))
			{
				return FALSE;
			}
			
			$pdo = UCLibPDOFactory::getPDO('mailqueue', '', 'invite2dbconfig');
			
			if($limit <= 0)
			{
				$limit = 20;
			}
			
			$sql = 'SELECT * FROM ' . $pdo->database . '.' . $pdo->table . ' LIMIT ?, ?';
			$params = array($start, $limit);
			$r = $pdo->query_with_prepare($sql, $params);
			
			return is_array($r) ? $r : FALSE;
		}
		
		/**
		 * 返回最后一条错误信息
		 * @return string
		 */
		public function errorInfo()
		{
			return $this->_error;
		}
		
		/**
		 * 随机取N个双向好友
		 * @param int $user_id 用户id
		 * @param int $limit 要取几个双向好友
		 * @return array
		 */
		public function getRandomFriends($user_id, $limit = 8)
		{
			$relation = new UCModRelation($user_id);
			//var_dump($relation->getBiRelation());
			
			//先取100个,从中随机取$limit个用户
			$friend_list = $relation->getBiRelation();
			$friend_list = $friend_list['entry'];
			
			$friend_show = array();
			$uid_list = array();
			
			if(!empty($friend_list))
			{
				//邀请随机取8个.
				shuffle($friend_list);			
				
				$friend_count = (count($friend_list) > $limit) ? $limit : count($friend_list);
				for($i = 0; $i < $friend_count; $i++)
				{
					//var_dump($friend_list[$i]);
					
					if(strlen($friend_list[$i]['fsdid']))
					{		
						$uid_list[] = $friend_list[$i]['fsdid'];
					}
				}
				
				$user_info = UCModUserInfo::getUserInfos($uid_list, array(USERINFO_NICKNAME, USERINFO_AVATAR_45));
				
				foreach($uid_list as $uid)
				{
					if(strlen($user_info[$uid][USERINFO_NICKNAME]) == 0 || strpos($user_info[$uid][USERINFO_AVATAR_45], 'girl_45x45') || strpos($user_info[$uid][USERINFO_AVATAR_45], 'boy_45x45') || strpos($user_info[$uid][USERINFO_AVATAR_45], 'default_45x45'))
					{
						continue;
					}
					else
					{
						$friend_show[] = array(
							'nickname' => $user_info[$uid][USERINFO_NICKNAME],
							'home_url' => get_user_home_url($uid),
							'face_url' => $user_info[$uid][USERINFO_AVATAR_45],
						);
					}
				}
			}
			
			return $friend_show;
		}
		
		/**
		 * 取N个系统推荐用户
		 * @param int $user_id 用户id
		 * @param int $limit 要取几个
		 * @return array
		 */
		public function getRecommendUsers($user_id, $limit = 8)
		{
			//$user_list = UCModUserSearcher::getRecommend($user_id, '', '', 0, $limit);
			include_once(dirname(__FILE__).'/../../models/user/UCModActiveUser.php');
			
			$user_list = UCModActiveUser::getRandomActiveUser('all', $limit);
			//var_dump($user_list);
			
			$account_list = array();
			
			if(is_array($user_list['rows']))
			{
				foreach($user_list['rows'] as $userInfo)
				{
					if(strlen($userInfo['user_id']))
					{
						$account_list[] = $userInfo['user_id'];
					}
				}
			}
			$user_list = array();
			
			$user_info = UCModUserInfo::getUserInfos($account_list, array(USERINFO_NICKNAME, USERINFO_AVATAR_45));
			
			foreach($account_list as $account)
			{
				if(strpos($user_info[$account][USERINFO_AVATAR_45], 'girl_45x45.gif') || strpos($user_info[$account][USERINFO_AVATAR_45], 'boy_45x45.gif'))
				{
				
				}
				else
				{
					$user_list[] = array(
						'nickname' => $user_info[$account][USERINFO_NICKNAME],
						'home_url' => get_user_home_url($account),
						'face_url' => $user_info[$account][USERINFO_AVATAR_45],
					);
				}
			}
			return $user_list;
		}
		
		/**
		 * 发站内APP邀请短信
		 * @param int $sender_uid	发送邀请者uid
		 * @param array $friend_list	要发送站内短信的好友列表 eg: $friend_list = array('123', '345', '567');
		 * @param array $app_info	app相关信息
		 *			eg: $app_info = array(
		 					'app_id' => '',	//应用ID
		 					'name' => '',	//应用名称
		 					'icon' => '',	//应用大图,
		 					'intro' => '',	//应用简介
		 					'n_playing' => '',	//当前我的好友中有多少人正在玩这个应用
		 				);
		 * @return boolean/Array()
		 */
		public static function send_appinvite_msg($sender_uid, $friend_list, $app_info)
		{
			$sender_uid = trim($sender_uid);
			if(strlen($sender_uid) == 0)
			{
				return FALSE;
			}
			if(!is_array($friend_list) || count($friend_list) == 0)
			{
				return FALSE;
			}
			if(!is_array($app_info))
			{
				return FALSE;
			}
			if(strlen($app_info['app_id']) == 0)
			{
				return FALSE;
			}
			$o_mgr = new UCModMessageMgr($sender_uid);
			
			//$app_id = UCModStore::getInstance()->getAppIdByOppId($app_info['app_id']);
			
			$app_id = $app_info['app_id'];
			
			$app_uc_info = UCModStore::getInstance()->getApp($app_id);
			
			if(!is_array($app_uc_info))
			{
				//无效应用
				return FALSE;
			}
			
			$app_show_url = UCModPanel::getLink($app_uc_info, TRUE);
			$app_show_url .= (strpos($app_show_url, '?') !== FALSE ? '&' : '?') . 'sdo_from=' . $sender_uid;
			
			$return_array = array();
			foreach($friend_list as $fuid)
			{
				$r = $o_mgr->sendRequest("play_game", $fuid, array("game_name" => $app_info['name'], "game_url" => $app_show_url, "game_pic" => UCModPanel::getIcon($app_id, '400'), "game_desc" => $app_info['intro'], "n_playing" => $app_info['n_playing']));
				$return_array[$fuid] = $r;
			}
			
			return $return_array;
		}
		
		public static function getInstance()
		{		
			if(self::$instance == null)
			{		
				self::$instance = new self;
			}
				
			return self::$instance;
		}
	}
?>